﻿#include "xrtc_client.h"

#include <sstream>

#include <QScreen>

#include<QThread>
#include<QMessageBox>


const float kMainWindowScale = 0.6;
const int kMaxStreamWindows = 2;
QWidget* stream_windows[kMaxStreamWindows] = { nullptr };

static QWidget* GetLocalVideo() {
    return stream_windows[0];
}

XRTCClient::XRTCClient(QWidget* parent)
    : QWidget(parent),
    xrtc_engine_(xrtc::CreateXRTCEngine(this))
{
    ui.setupUi(this);

    // 设置窗口大小为屏幕大小的60%
    QScreen* screen = QGuiApplication::primaryScreen();
    int width = screen->geometry().width() * kMainWindowScale;
    int height = screen->geometry().height() * kMainWindowScale;
    this->resize(width, height);
    this->setMinimumSize(QSize(width / 2, height / 2));

    // 顶部右侧布局
    InitStreamWindows(kMaxStreamWindows);
    
    // 展示音频和视频设备列表信息
    InitDeviceInfo();

    ConnectSlot();
}

XRTCClient::~XRTCClient()
{
    
}

void XRTCClient::OpenCamSource() {
    if (!cam_source_) {
        xrtc::XRTCVideoConfig video_config;
        video_config.device_id = ui.cb_cam->currentData().toString().toUtf8();
        cam_source_ = xrtc_engine_->CreateVideoSource(video_config);
        cam_source_->Start();
    }
#if 0
    else {
        cam_source_->Stop();
        xrtc_engine_->DestroyVideoSource(cam_source_);
        cam_source_ = nullptr;
    }
#endif 
}

void XRTCClient::CloseCamSource()
{
    if (cam_source_) {
        cam_source_->Stop();
        xrtc_engine_->DestroyVideoSource(cam_source_);
        cam_source_ = nullptr;
    }
}

void XRTCClient::OpenPreview() {
    if (!cam_source_) {
        QMessageBox::warning(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("本地视频预览失败，没有输入源"));
        return;
    }

    if (!local_video_preview_) {
        xrtc::XRTCCanvas canvas;
        canvas.view = (void*)GetLocalVideo()->winId();
        local_video_preview_ = xrtc_engine_->CreatePreview(cam_source_,canvas);
        local_video_preview_->Start();
    }
}

void XRTCClient::ClosePreview()
{
    if (local_video_preview_) {
        local_video_preview_->Stop();
        xrtc_engine_->DestroyPreview(local_video_preview_);
        local_video_preview_ = nullptr;
    }
}

#if 0

void XRTCClient::ClickBtnPush() {
    ui.btn_push->setDisabled(true);

    if (!cam_source_) {
        ui.btn_push->setDisabled(false);
        SetTips("推流失败，没有视频源", true);
        return;
    }

    if (!xrtc_pusher_) { // 开始推流
        xrtc_pusher_ = xrtc_engine_->CreatePusher();
#if 0
        // 推流url地址
        std::stringstream ss;
        ss << "xrtc://" << ui.edit_host->text().toLocal8Bit().data()
           << "/push?uid=" << ui.edit_uid->text().toLocal8Bit().data()
           << "&streamName=" << ui.edit_stream_name->text().toLocal8Bit().data()
           << "&audio=1&video=1&isDtls=1";

        xrtc_pusher_->StartPush(ss.str(), cam_source_);
#endif
        xrtc::XRTCCanvas canvas;
        QWidget* remote_video = stream_windows[1];
        canvas.view = (void*)remote_video->winId();
        xrtc_pusher_->StartPush("ws://192.168.10.251:9002",cam_source_,canvas);
    }
    else {
        xrtc_pusher_->StopPush();
    }

    ui.btn_push->setDisabled(false);
}
voidXRTCClient::ClickBtnPull() {
    ui.btn_pull->setDisabled(true);

    if (!xrtc_player_) {
        xrtc_player_ = xrtc_engine_->CreatePlayer();

        xrtc::XRTCCanvas canvas;
        QWidget* remote_video = stream_windows[1];
        canvas.view = (void*)remote_video->winId();

        xrtc_player_->StartPull("ws://192.168.10.251:9002", canvas);
    }
    else {
        xrtc_player_->StopPull();
    }

    ui.btn_pull->setDisabled(false);


}
#endif 

void XRTCClient:: ClickBtnJoin() {
    ui.btn_join->setDisabled(true);
    
    OpenCamSource();
    
    ui.btn_join->setDisabled(false);
}

void XRTCClient::ClickBtnLeave()
{
    ui.btn_leave->setDisabled(true);
    if (!in_room_) {
        ui.btn_leave->setDisabled(false);
        return;
    }

    QMetaObject::invokeMethod(this, [=]() {
        if (local_video_preview_) {
            local_video_preview_->Stop();
        }

        if (xrtc_pusher_) {
            xrtc_pusher_->StopPush();
        }
        if (cam_source_) {
            cam_source_->Stop();
        }

        });



    ui.btn_leave->setDisabled(false);
}

void XRTCClient::closeEvent(QCloseEvent* event)
{

    //让出时间清理资源
    if (local_video_preview_) {
        local_video_preview_->Stop();
    }
    if (xrtc_pusher_) {
        xrtc_pusher_->StopPush();
        QThread::msleep(500);
    }


    if (cam_source_) {
        cam_source_->Stop();
        QThread::msleep(500);
    }



    QWidget::closeEvent(event);
}

void XRTCClient::InitStreamWindows(int num) {
    bootomLayout = new QHBoxLayout;
    bootomLayout->setSpacing(1);
    bootomLayout->setContentsMargins(1, 1, 1, 1);
    ui.BottomWidget->setLayout(bootomLayout);

    int cols = sqrt(num);
    for (int i = 0; i < num; ++i) {
        stream_windows[i] = new QWidget();
        stream_windows[i]->setStyleSheet("background-color: #252526;");
        bootomLayout->addWidget(stream_windows[i]);
    }
}

void XRTCClient::InitDeviceInfo() {
    std::vector<xrtc::XRTCDeviceInfo> device_list =
        xrtc_engine_->GetVideoDeviceList();
    for (auto info : device_list) {
        ui.cb_cam->addItem(QString(info.device_name.c_str()),
            info.device_id.c_str());
    }

    device_list = xrtc_engine_->GetAudioDeviceList();
    for (auto info : device_list) {
        ui.cb_mic->addItem(QString(info.device_name.c_str()),
            info.device_id.c_str());
    }
}

void XRTCClient::ConnectSlot() {
    connect(ui.btn_join, SIGNAL(clicked()), this, SLOT(ClickBtnJoin()));
    connect(ui.btn_leave, SIGNAL(clicked()), this, SLOT(ClickBtnLeave()));
}

void XRTCClient::SetTips(const std::string& tips, bool is_error) {
#if 0
    if (is_error) {
        ui.label_tips2->setStyleSheet("color: red");
    }
    else {
        ui.label_tips2->setStyleSheet("color: white");
    }

    ui.label_tips2->setText(QString::fromLocal8Bit(tips.c_str()));
#endif 
}

void XRTCClient::resizeEvent(QResizeEvent* event) {
    if (local_video_preview_) {
        local_video_preview_->Resize();
    }
}

void XRTCClient::OnVideoSourceStartEvent(xrtc::IXRTCMediaSource* video_source, 
    xrtc::XRTCError err) 
{
    QMetaObject::invokeMethod(this, [=]() {
        if (err == xrtc::XRTCError::kNoErr) {
            if (!xrtc_pusher_) { // 开始推流
                xrtc_pusher_ = xrtc_engine_->CreatePusher();

                xrtc::XRTCCanvas canvas;
                QWidget* remote_video = stream_windows[1];
                canvas.view = (void*)remote_video->winId();
                
                QByteArray uid_utf8 = ui.edit_uid->text().toUtf8();
                std::string uid(uid_utf8.constData(), uid_utf8.size());

                QByteArray room_utf8 = ui.edit_room->text().toUtf8();
                std::string roomId(room_utf8.constData(), room_utf8.size());

                xrtc_pusher_->StartPush("ws://192.168.10.251:9002", cam_source_, canvas,uid,roomId);
            }
            ui.btn_join->setDisabled(false);
        }
        else {
            QMessageBox::warning(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("打开视频源失败"));
            CloseCamSource();
        }
    });
}

void XRTCClient::OnVideoSourceStopEvent(xrtc::IXRTCMediaSource* video_source, 
    xrtc::XRTCError err) 
{
    QMetaObject::invokeMethod(this, [=]() {
        if (err == xrtc::XRTCError::kNoErr) {
            xrtc_engine_->DestroyVideoSource(cam_source_);
            cam_source_ = nullptr;
        }
        else {
            QMessageBox::warning(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("关闭视频源失败"));
        }
    });
}

void XRTCClient::OnPushStreamState(xrtc::IXRTCPusher* pusher, 
    xrtc::XRTCStreamState state) 
{
#if 0
    QMetaObject::invokeMethod(this, [=]() {
        if (state == xrtc::XRTCStreamState::kConnecting) {
            ui.btn_push->setText(QString::fromLocal8Bit("停止推流"));
            ui.btn_push->setStyleSheet(kBgStop);
            SetTips("推流中...");
        } else if (state == xrtc::XRTCStreamState::kConnected) {
            ui.btn_push->setText(QString::fromLocal8Bit("停止推流"));
            ui.btn_push->setStyleSheet(kBgStop);
            SetTips("推流成功");
        }
        else if (state == xrtc::XRTCStreamState::kDisconnected) {
            ui.btn_push->setText(QString::fromLocal8Bit("停止推流"));
            ui.btn_push->setStyleSheet(kBgStop);
            SetTips("推流断开", true);
        }
        else if (state == xrtc::XRTCStreamState::kFailed) {
            ui.btn_push->setText(QString::fromLocal8Bit("开始推流"));
            ui.btn_push->setStyleSheet(kBgStart);
            SetTips("推流失败", true);
        }
        });
#endif
}

void XRTCClient::OnStartPushEvent(xrtc::IXRTCPusher* pusher, 
    xrtc::XRTCError err) 
{
    QMetaObject::invokeMethod(this, [=]() {
        if (err != xrtc::XRTCError::kNoErr) {
            QMessageBox::warning(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("加入房间失败"));
            return;
        }
        else {
            OpenPreview();
            in_room_ = true;
            ui.btn_join->setDisabled(true);
            ui.btn_leave->setDisabled(false);
        }
    });
}

void XRTCClient::OnStopPushEvent(xrtc::IXRTCPusher* pusher, 
    xrtc::XRTCError err) 
{
    QMetaObject::invokeMethod(this, [=]() {
        if (err != xrtc::XRTCError::kNoErr) {
            QMessageBox::warning(this, QString::fromLocal8Bit("警告"), QString::fromLocal8Bit("离开房间失败!"));
            in_room_ = false;
            return;
        }
        else{
            xrtc_engine_->DestroyPusher(xrtc_pusher_);
            xrtc_pusher_ = nullptr;

            this->update();
            ui.btn_join->setDisabled(false);
            ui.btn_leave->setDisabled(true);

            //注意先preview和pusher先Stop再Destroy
            xrtc_engine_->DestroyPreview(local_video_preview_);
            local_video_preview_ = nullptr;
            in_room_ = false;
        }

    });

}

void XRTCClient::OnPullStreamState(xrtc::IXRTCPlayer* player, xrtc::XRTCStreamState state)
{
#if 0
    QMetaObject::invokeMethod(this, [=]() {
        if (state == xrtc::XRTCStreamState::kConnecting) {
            ui.btn_pull->setText(QString::fromLocal8Bit("停止拉流"));
            ui.btn_pull->setStyleSheet(kBgStop);
            SetTips("拉流中...");
        }
        else if (state == xrtc::XRTCStreamState::kConnected) {
            ui.btn_pull->setText(QString::fromLocal8Bit("停止拉流"));
            ui.btn_pull->setStyleSheet(kBgStop);
            SetTips("拉流成功");
        }
        else if (state == xrtc::XRTCStreamState::kDisconnected) {
            ui.btn_pull->setText(QString::fromLocal8Bit("停止拉流"));
            ui.btn_pull->setStyleSheet(kBgStop);
            SetTips("拉流断开", true);
        }
        else if (state == xrtc::XRTCStreamState::kFailed) {
            ui.btn_pull->setText(QString::fromLocal8Bit("开始拉流"));
            ui.btn_pull->setStyleSheet(kBgStart);
            SetTips("拉流失败", true);

            xrtc_player_->StopPull();
            xrtc_engine_->DestroyPlayer(xrtc_player_);
            xrtc_player_ = nullptr;
        }
        });
#endif 
}

void XRTCClient::OnStartPullEvent(xrtc::IXRTCPlayer* player, xrtc::XRTCError err)
{
#if 0
    QMetaObject::invokeMethod(this, [=]() {
        if (err != xrtc::XRTCError::kNoErr) {
            ui.btn_pull->setText(QString::fromLocal8Bit("开始拉流"));
            ui.btn_pull->setStyleSheet(kBgStart);
            std::string tips = "拉流失败，err_no: " +
                std::to_string((int)err);
            SetTips(tips, true);

            xrtc_engine_->DestroyPlayer(xrtc_player_);
            xrtc_player_ = nullptr;
        }
        });
#endif 
}

void XRTCClient::OnStopPullEvent(xrtc::IXRTCPlayer* player, xrtc::XRTCError err)
{
#if 0
    QMetaObject::invokeMethod(this, [=]() {
        if (err != xrtc::XRTCError::kNoErr) {
            ui.btn_pull->setText(QString::fromLocal8Bit("停止拉流"));
            ui.btn_pull->setStyleSheet(kBgStop);
            std::string tips = "停止拉流失败，err_no: " +
                std::to_string((int)err);
            SetTips(tips, true);
        }
        else {
            ui.btn_pull->setText(QString::fromLocal8Bit("开始拉流"));
            ui.btn_pull->setStyleSheet(kBgStart);
            SetTips("停止拉流成功");
        }
        });

    xrtc_engine_->DestroyPlayer(xrtc_player_);
    xrtc_player_ = nullptr;
#endif 
}

void XRTCClient::OnRemotePeerLeaveEvent()
{
    QMetaObject::invokeMethod(this, [=]() {
        if (local_video_preview_) {
            local_video_preview_->Stop();
        }
        if (xrtc_pusher_) {
            xrtc_pusher_->StopPush();
        }
        if (cam_source_) {
            cam_source_->Stop();
        }
    });

}
